﻿using jvm.instructions.common;
using jvm.rtda;
using jvm.rtda.frame;
using jvm.rtda.heap;
using jvm.rtda.heap.clazz;
using jvm.rtda.heap.clazz.cp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace jvm.instructions.references
{
    class MULTI_ANEW_ARRAY : Instruction
    {
        public ushort index;
        public byte dimensions;

        public override void FetchOperands(ByteCodeReader reader)
        {
            index = reader.ReadUint16();
            dimensions = reader.ReadUint8();
        }

        public override void Execute(JFrame frame)
        {
            JConstantPool pool = frame.method.jClass.constantPool;
            ClassRef classRef = pool.GetConstant<ClassRef>(index);
            JClass jClass = classRef.ResolvedClass();

            JOperandStack stack = frame.operandStack;
            List<int> counts = PopCheckCounts(stack, dimensions);
            JObject obj = NewMultiArray(counts, jClass);
            stack.PushRef(obj);
        }

        List<int> PopCheckCounts(JOperandStack stack, byte dimensions)
        {
            List<int> counts = new List<int>();
            for (byte i = 0; i < dimensions; i++)
            {
                counts[i] = stack.PopInt();
                if (counts[i] < 0)
                {
                    Console.WriteLine("java.lang.NegativeArraySizeException");
                    Environment.Exit(0);
                }
            }
            return counts;
        }

        // 除了最后一层的值，外面几层都初始化掉
        JObject NewMultiArray(List<int> counts, JClass jClass)
        {
            JObject obj = jClass.NewArray((uint)counts[0]);
            if (counts.Count > 1)
            {
                for (int i = 0; i < counts[0]; i++)
                {
                    obj.Refs()[i] = NewMultiArray((List<int>)counts.Skip(1), jClass.GetInnerClass());
                }
            }
            return obj;
        }

    }
}
